package com.chaoxi.picturebackend.utils;

import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javax.persistence.Column;
import javax.persistence.Table;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

public class ExportUtils {

    // 默认排除的字段
    private static final Set<String> DEFAULT_EXCLUDE_FIELDS = new HashSet<>(
            Arrays.asList("password")
    );

    // 日期时间格式化器
    private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    /**
     * 导出数据到Excel（通过HttpServletResponse输出）
     */
    public static <T> void exportData(HttpServletResponse response, List<T> dataList, Class<T> entityClass) throws IOException {
        exportData(response, dataList, entityClass, null, null, null);
    }

    /**
     * 导出数据到Excel（通过HttpServletResponse输出），支持自定义选项
     */
    public static <T> void exportData(HttpServletResponse response, List<T> dataList, Class<T> entityClass,
                                      Set<String> excludeFields, String sheetName, String fileName) throws IOException {
        Workbook workbook = createWorkbook(dataList, entityClass, excludeFields, sheetName);

        // 设置响应头信息
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("UTF-8");

        // 获取文件名
        if (fileName == null || fileName.trim().isEmpty()) {
            Table tableAnnotation = entityClass.getAnnotation(Table.class);
            fileName = (tableAnnotation != null && !tableAnnotation.name().isEmpty()) ?
                    tableAnnotation.name() : entityClass.getSimpleName();
        }

        String encodedFileName = URLEncoder.encode(fileName, "UTF-8");
        response.setHeader("Content-Disposition", "attachment; filename=" + encodedFileName + ".xlsx");

        // 将Excel写入响应输出流
        workbook.write(response.getOutputStream());
        workbook.close();
    }

    /**
     * 导出数据到Excel文件（保存到本地文件系统）
     */
    public static <T> void exportToFile(String filePath, List<T> dataList, Class<T> entityClass) throws IOException {
        exportToFile(filePath, dataList, entityClass, null, null);
    }

    /**
     * 导出数据到Excel文件（保存到本地文件系统），支持自定义选项
     */
    public static <T> void exportToFile(String filePath, List<T> dataList, Class<T> entityClass,
                                        Set<String> excludeFields, String sheetName) throws IOException {
        // 确保目录存在
        File file = new File(filePath);
        File parentDir = file.getParentFile();
        if (parentDir != null && !parentDir.exists()) {
            boolean created = parentDir.mkdirs();
            if (!created) {
                throw new IOException("无法创建目录: " + parentDir.getAbsolutePath());
            }
        }

        Workbook workbook = createWorkbook(dataList, entityClass, excludeFields, sheetName);

        try (OutputStream out = new FileOutputStream(file)) {
            workbook.write(out);
        } finally {
            workbook.close();
        }
    }

    /**
     * 创建Excel工作簿
     */
    private static <T> Workbook createWorkbook(List<T> dataList, Class<T> entityClass,
                                               Set<String> excludeFields, String sheetName) {
        Workbook workbook = new XSSFWorkbook();

        // 获取工作表名称
        if (sheetName == null || sheetName.trim().isEmpty()) {
            Table tableAnnotation = entityClass.getAnnotation(Table.class);
            sheetName = (tableAnnotation != null && !tableAnnotation.name().isEmpty()) ?
                    tableAnnotation.name() : entityClass.getSimpleName();
        }

        Sheet sheet = workbook.createSheet(sheetName);

        // 获取需要导出的字段列表
        List<Field> exportFields = getExportFields(entityClass, excludeFields);

        // 创建标题行
        createHeaderRow(workbook, sheet, exportFields);

        // 填充数据行
        if (dataList != null && !dataList.isEmpty()) {
            fillDataRows(workbook, sheet, dataList, exportFields);
        }

        // 自动调整列宽
        autoSizeColumns(sheet, exportFields.size());

        return workbook;
    }

    /**
     * 获取需要导出的字段列表
     */
    private static <T> List<Field> getExportFields(Class<T> entityClass, Set<String> excludeFields) {
        Set<String> finalExcludeFields = excludeFields != null ? excludeFields : DEFAULT_EXCLUDE_FIELDS;

        return Arrays.stream(entityClass.getDeclaredFields())
                .filter(field -> {
                    Column columnAnnotation = field.getAnnotation(Column.class);
                    return columnAnnotation != null && !finalExcludeFields.contains(field.getName());
                })
                .collect(Collectors.toList());
    }

    /**
     * 创建标题行
     */
    private static void createHeaderRow(Workbook workbook, Sheet sheet, List<Field> exportFields) {
        Row headerRow = sheet.createRow(0);
        CellStyle headerStyle = createHeaderCellStyle(workbook);

        AtomicInteger colIndex = new AtomicInteger(0);
        exportFields.forEach(field -> {
            Column columnAnnotation = field.getAnnotation(Column.class);
            String columnName = columnAnnotation.name();

            Cell cell = headerRow.createCell(colIndex.getAndIncrement());
            cell.setCellValue(columnName);
            cell.setCellStyle(headerStyle);
        });
    }

    /**
     * 创建标题行单元格样式
     */
    private static CellStyle createHeaderCellStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        Font font = workbook.createFont();
        font.setBold(true);
        font.setColor(IndexedColors.WHITE.getIndex());
        style.setFont(font);
        style.setFillForegroundColor(IndexedColors.DARK_BLUE.getIndex());
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        style.setAlignment(HorizontalAlignment.CENTER);
        return style;
    }

    /**
     * 填充数据行
     */
    private static <T> void fillDataRows(Workbook workbook, Sheet sheet, List<T> dataList, List<Field> exportFields) {
        CellStyle dataStyle = createDataCellStyle(workbook);
        CellStyle dateStyle = createDateCellStyle(workbook);

        for (int i = 0; i < dataList.size(); i++) {
            T data = dataList.get(i);
            // +1 因为第一行是标题
            Row row = sheet.createRow(i + 1);

            for (int j = 0; j < exportFields.size(); j++) {
                Field field = exportFields.get(j);
                Cell cell = row.createCell(j);

                Object value = getFieldValue(data, field);
                setCellValue(cell, value, field.getType());

                // 应用样式
                if (isDateType(field.getType())) {
                    cell.setCellStyle(dateStyle);
                } else {
                    cell.setCellStyle(dataStyle);
                }
            }
        }
    }

    /**
     * 创建数据单元格样式
     */
    private static CellStyle createDataCellStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.LEFT);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);
        return style;
    }

    /**
     * 创建日期单元格样式
     */
    private static CellStyle createDateCellStyle(Workbook workbook) {
        CellStyle style = workbook.createCellStyle();
        style.setAlignment(HorizontalAlignment.CENTER);
        style.setVerticalAlignment(VerticalAlignment.CENTER);
        style.setBorderTop(BorderStyle.THIN);
        style.setBorderBottom(BorderStyle.THIN);
        style.setBorderLeft(BorderStyle.THIN);
        style.setBorderRight(BorderStyle.THIN);

        // 创建日期格式
        CreationHelper createHelper = workbook.getCreationHelper();
        short dateFormat = createHelper.createDataFormat().getFormat("yyyy-mm-dd hh:mm:ss");
        style.setDataFormat(dateFormat);

        return style;
    }

    /**
     * 获取字段值
     */
    private static <T> Object getFieldValue(T data, Field field) {
        try {
            field.setAccessible(true);
            return field.get(data);
        } catch (IllegalAccessException e) {
            // 尝试通过getter方法获取值
            try {
                String fieldName = field.getName();
                String getterName = "get" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);
                Method getter = data.getClass().getMethod(getterName);
                return getter.invoke(data);
            } catch (Exception ex) {
                return null;
            }
        }
    }

    /**
     * 设置单元格值
     */
    private static void setCellValue(Cell cell, Object value, Class<?> fieldType) {
        if (value == null) {
            cell.setCellValue("");
            return;
        }

        if (fieldType == String.class) {
            cell.setCellValue((String) value);
        } else if (fieldType == Integer.class || fieldType == int.class) {
            cell.setCellValue((Integer) value);
        } else if (fieldType == Long.class || fieldType == long.class) {
            cell.setCellValue((Long) value);
        } else if (fieldType == Double.class || fieldType == double.class) {
            cell.setCellValue((Double) value);
        } else if (fieldType == Float.class || fieldType == float.class) {
            cell.setCellValue((Float) value);
        } else if (fieldType == Boolean.class || fieldType == boolean.class) {
            cell.setCellValue((Boolean) value);
        } else if (fieldType == Date.class) {
            cell.setCellValue((Date) value);
        } else if (fieldType == LocalDateTime.class) {
            cell.setCellValue(((LocalDateTime) value).format(DATE_TIME_FORMATTER));
        } else if (fieldType == LocalDate.class) {
            cell.setCellValue(((LocalDate) value).format(DATE_FORMATTER));
        } else {
            cell.setCellValue(value.toString());
        }
    }

    /**
     * 判断是否为日期类型
     */
    private static boolean isDateType(Class<?> type) {
        return type == Date.class || type == LocalDateTime.class || type == LocalDate.class;
    }

    /**
     * 自动调整列宽
     */
    private static void autoSizeColumns(Sheet sheet, int columnCount) {
        for (int i = 0; i < columnCount; i++) {
            sheet.autoSizeColumn(i);
            // 设置最小列宽
            if (sheet.getColumnWidth(i) < 3000) {
                sheet.setColumnWidth(i, 3000);
            }
            // 设置最大列宽
            if (sheet.getColumnWidth(i) > 15000) {
                sheet.setColumnWidth(i, 15000);
            }
        }
    }

    /**
     * 添加统计行（示例方法，可根据需要扩展）
     */
    public static <T> void addSummaryRow(Sheet sheet, List<T> dataList, List<Field> exportFields, String summaryText) {
        if (dataList == null || dataList.isEmpty()) {return;}

        int lastRowNum = sheet.getLastRowNum();
        Row summaryRow = sheet.createRow(lastRowNum + 1);

        CellStyle summaryStyle = sheet.getWorkbook().createCellStyle();
        Font font = sheet.getWorkbook().createFont();
        font.setBold(true);
        font.setColor(IndexedColors.RED.getIndex());
        summaryStyle.setFont(font);

        Cell cell = summaryRow.createCell(0);
        cell.setCellValue(summaryText);
        cell.setCellStyle(summaryStyle);

        // 合并单元格
        sheet.addMergedRegion(new CellRangeAddress(lastRowNum + 1, lastRowNum + 1, 0, exportFields.size() - 1));
    }
}